package com.xbongbong.paas.service.stage.execute;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessDataEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.StageWorkLogEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasProcessTemplateEntityExt;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.StageTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.WorkflowTransferHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasProcessDataModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.dto.StartProcessDTO;
import com.xbongbong.paas.pojo.vo.StartProcessVO;
import com.xbongbong.paas.service.ProModelService;
import com.xbongbong.paas.service.stage.StageJumpHandle;
import com.xbongbong.paas.service.workflow.trigger.WorkflowFormDataOperationService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.businessrule.pojo.BusinessRuleInfoPojo;
import com.xbongbong.pro.businesstage.pojo.dto.CommonJumpDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageFinishWorkDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageGetDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageJumpDealDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageJumpSpecialDealDTO;
import com.xbongbong.pro.businesstage.pojo.dto.StageJumpValidateDTO;
import com.xbongbong.pro.businesstage.pojo.vo.StageFinishWorkVO;
import com.xbongbong.pro.businesstage.pojo.vo.StageGetVO;
import com.xbongbong.pro.constant.CommonConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.constant.SymbolConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.PaasStageEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.BomErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ClueErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.workflow.TriggerEventTypeEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.log.pojo.DetailLogPojo;
import com.xbongbong.pro.message.constant.CluePushConstant;
import com.xbongbong.pro.message.enums.PushTypeEnum;
import com.xbongbong.pro.message.help.PushHelper;
import com.xbongbong.pro.message.pojo.PushRefTypePojo;
import com.xbongbong.pro.message.pojo.dto.MessageRabbitMqDTO;
import com.xbongbong.pro.rabbitmq.producer.BaseProducer;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.weblist.pojo.dto.SaasBaseDTO;
import com.xbongbong.pro.workflow.enums.WorkflowExecutionTypeEnum;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.process.operate.ProcessStartHelp;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ClueStageEntity;
import com.xbongbong.saas.domain.entity.ClueStageLogEntity;
import com.xbongbong.saas.domain.entity.ClueUserEntity;
import com.xbongbong.saas.domain.entity.ClueWorkLogEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.ClueEntityExt;
import com.xbongbong.saas.enums.ClueRuleSettingEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.ProjectLogEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.dictionary.ClueStatusEnum;
import com.xbongbong.saas.enums.dictionary.DictionaryEnum;
import com.xbongbong.saas.help.workflow.MarketActivityForStaticHelp;
import com.xbongbong.saas.model.ClueModel;
import com.xbongbong.saas.model.ClueStageLogModel;
import com.xbongbong.saas.model.ClueStageModel;
import com.xbongbong.saas.model.ClueUserModel;
import com.xbongbong.saas.model.ClueWorkLogModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.service.CustomerCommunicateService;
import com.xbongbong.saas.service.DictionaryService;
import com.xbongbong.saas.service.ScoreCalculateService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowExecutionEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTransferDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.model.WorkflowTransferDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.WorkflowRabbitmqDTO;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.nodes.FormTriggerNode;
import com.xbongbong.workflow.producer.WorkflowProducer;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;


/**
 * @author 吴峰
 * @date 2021/11/22 19:26
 */
@Slf4j
@Service("clueStageExecuteHandleImpl")
public class ClueStageExecuteHandleImpl extends AbstractStageExecuteHandle {

    @Resource
    private ClueStageLogModel clueStageLogModel;
    @Resource
    private ClueStageModel clueStageModel;
    @Resource
    private ClueModel clueModel;
    @Resource
    private ClueWorkLogModel clueWorkLogModel;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private ScoreCalculateService scoreCalculateService;
    @Resource
    private ProModelService proModelService;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private PushHelper pushHelper;
    @Resource
    @Lazy
    private CustomerCommunicateService customerCommunicateService;
    @Resource
    private BaseProducer baseProducer;
    @Resource
    private DictionaryService dictionaryService;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private WorkflowFormDataOperationService workflowFormDataOperationService;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private ClueUserModel clueUserModel;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private WorkflowProducer workflowProducer;
    @Resource
    private ProcessStartHelp processStartHelp;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private PaasProcessDataModel paasProcessDataModel;
    @Resource
    private WorkflowTransferDataModel workflowTransferDataModel;
    @Resource
    private Map<Integer, StageJumpHandle> stageJumpMap;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private MarketActivityForStaticHelp marketActivityForStaticHelp;
    @Resource
    private IndexTypeModel indexTypeModel;

    @Override
    public Integer type() {
        return XbbRefTypeEnum.CLUE.getCode();
    }

    @Override
    public void validate(StageJumpValidateDTO stageJumpValidateDTO) throws XbbException {
        String corpid = stageJumpValidateDTO.getCorpid();
        Long clueId = stageJumpValidateDTO.getDataId();
        PaasStageEntity toStageEntity = stageJumpValidateDTO.getToStageEntity();
        ClueEntityExt clueEntityExt = clueModel.getByKey(clueId, corpid);
        //公海线索不允许更改线索阶段
        Integer isPublic = clueEntityExt.getData().getInteger(ClueEnum.IS_PUBLIC.getAttr());
        if (Objects.equals(isPublic, 1)) {
            throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111001);
        }
        String status = clueEntityExt.getData().getString(ClueEnum.CLUE_STATUS.getAttr());
        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(clueEntityExt.getFormId(), clueEntityExt.getCorpid());
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
        if (Objects.nonNull(toStageEntity)) {
            // 已转换客户的线索不能跳入失败阶段
            if (Objects.equals(toStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType())) {
                if (Objects.equals(status, ClueStatusEnum.TRANSFORMED.getCode())) {
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                    boolQueryBuilder.filter(termsQuery(StringConstant.DEL, Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.DELETE.getDel())));
                    boolQueryBuilder.filter(termQuery(CustomerManagementEnum.getEsAttr4Keyword(CustomerManagementEnum.CLUE_ID), clueId));
                    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                    sourceBuilder.query(boolQueryBuilder);
                    IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                    SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
                    searchRequest.source(sourceBuilder);
                    CountRequest countRequest = new CountRequest(searchRequest.indices()[0]);
                    countRequest.query(searchRequest.source().query());
                    Long count = xbbElasticsearchRestTemplate.count(countRequest);
                    if (Objects.nonNull(count) && count > 0) {
                        throw new XbbException(ClueErrorCodeEnum.API_ERROR_1110024);
                    }
                }

                FieldAttrEntity fieldAttrEntity = explainMap.getOrDefault(ClueEnum.INVALID_REASON.getAttr(), new FieldAttrEntity());
                boolean wastage = Objects.equals(fieldAttrEntity.getRequired(), 1) && Objects.equals(fieldAttrEntity.getIsOpen(), 1) && Objects.equals(fieldAttrEntity.getVisible(), 1);
                if (wastage && (Objects.isNull(stageJumpValidateDTO.getReasonId()) || stageJumpValidateDTO.getReasonId() <= 0)) {
                    //无效原因必填
                    throw new XbbException(ClueErrorCodeEnum.API_ERROR_1110002);
                }
                FieldAttrEntity memoField = explainMap.getOrDefault(ClueEnum.INVALID_MEMO.getAttr(), new FieldAttrEntity());
                boolean memoRequired = Objects.equals(memoField.getRequired(), 1) && Objects.equals(memoField.getIsOpen(), 1) && Objects.equals(memoField.getVisible(), 1);
                if (memoRequired && StringUtil.isEmpty(stageJumpValidateDTO.getMemo())) {
                    throw new XbbException(BomErrorCodeEnum.API_ERROR_242019);
                }
            }
        }
    }

    @Override
    public StageGetVO get(StageGetDTO stageGetDTO) throws XbbException {
        StageGetVO stageGetVO = new StageGetVO();
        stageGetVO.setStageShowType(0);
        String corpid = stageGetDTO.getCorpid();
        Long formId = stageGetDTO.getFormId();
        Long dataId = stageGetDTO.getDataId();
        Integer saasMark = stageGetDTO.getSaasMark();
        ClueEntityExt clueEntityExt = new ClueEntityExt();

        //老审批流转状态
        Integer approveFlowStatus = null;
        //工作流审批流转状态
        Integer workflowFlowStatus = null;

        if (Objects.equals(stageGetDTO.getApproveType(), BasicConstant.ONE)) {
            PaasProcessDataEntity processDataEntity = paasProcessDataModel.getByTaskId(stageGetDTO.getProcessTaskId(), corpid);
            clueEntityExt.setData(JSONObject.parseObject(processDataEntity.getData()));
            approveFlowStatus = processDataEntity.getFlowStatus();
        } else if (Objects.equals(stageGetDTO.getApproveType(), BasicConstant.TWO)) {
            WorkflowTransferDataEntity workflowTransferDataEntity = workflowTransferDataModel.getByTaskId(stageGetDTO.getProcessTaskId(), corpid);
            JSONObject workFlowData = workflowTransferDataEntity.getData();
            JSONObject dataJSONObject = workFlowData.getJSONObject("data");
            clueEntityExt.setData(dataJSONObject.getJSONObject("data"));
            WorkflowTaskEntity workflowTaskEntity = workflowTaskModel.getByKey(stageGetDTO.getProcessTaskId(), corpid);
            workflowFlowStatus = Objects.isNull(workflowTaskEntity) ? null : workflowTaskEntity.getFlowStatus();
        } else {
            clueEntityExt = clueModel.getByKey(dataId, corpid);
            // 移动端透传关联数据时入参取不到最新formid
            formId = clueEntityExt.getFormId();
        }
        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);

        boolean checkshow = checkshow(stageGetDTO, clueEntityExt);
        if (!checkshow) {
            return stageGetVO;
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Long stageProcessId = clueEntityExt.getData().getLong(ClueEnum.STAGE_PROCESS_ID.getAttr());
        String clueStage = clueEntityExt.getData().getString(ClueEnum.CLUE_STAGE.getAttr());
        StageProcessEntity stageProcessEntity = getStageProcessEntity(stageGetDTO, stageProcessId, clueStage, explainMap, clueEntityExt);
        if (Objects.isNull(stageProcessEntity)) {
            return stageGetVO;
        }
        stageProcessId = stageProcessEntity.getId();
        List<ClueStageLogEntity> clueStageLogEntities = new ArrayList<>();
        if (Objects.nonNull(dataId) && !Objects.equals(dataId, BasicConstant.ZERO_LONG)) {
            params.put("corpid", corpid);
            params.put("formId", formId);
            params.put("del", 0);
            params.put("dataId", dataId);
            clueStageLogEntities = clueStageLogModel.findEntitys(params);
        }
        params.clear();
        params.put("corpid", corpid);
        params.put("formId", formId);
        params.put("stageProcessId", stageProcessId);
        params.put("del", 0);
        params.put("orderByStr", "sort desc,add_time asc");
        List<ClueStageEntity> clueStageEntities = clueStageModel.findEntitys(params);
        Integer stageRation = clueEntityExt.getData().getInteger(ClueEnum.STAGE_RATIO.getAttr());
        // 主逻辑
        stageGetVO = stageGet(stageRation, clueEntityExt, stageProcessEntity, stageGetDTO, clueStageLogEntities, clueStageEntities, approveFlowStatus, workflowFlowStatus);
        stageGetVO.setStageProcessId(stageProcessId);
        // 失败阶段的弹框解释
        List<FieldAttrEntity> explainList = new ArrayList<>();
        explainList.add(explainMap.get(ClueEnum.INVALID_REASON.getAttr()));
        explainList.add(explainMap.get(ClueEnum.INVALID_MEMO.getAttr()));
        stageGetVO.setExplainList(explainList);

        JSONObject data = clueEntityExt.getData();
        String clueStatus = FastJsonHelper.getStringOrDefaultFromFormData(data, ClueEnum.CLUE_STATUS.getAttr(), "");
        if (!Objects.equals(clueStatus, ClueStatusEnum.TRANSFORMED.getCode())) {
            // 不是已转化客户的线索，就让前端弹框
            stageGetVO.setAllowTransCustomer(1);
        }
        return stageGetVO;
    }

    @Override
    public StageFinishWorkVO finishWork(StageFinishWorkDTO stageFinishWorkDTO) throws XbbException {
        String corpid = stageFinishWorkDTO.getCorpid();
        Long dataId = stageFinishWorkDTO.getDataId();
        Long formId = stageFinishWorkDTO.getFormId();
        StageFinishWorkVO stageFinishWorkVO = stageFinishWork(stageFinishWorkDTO);
        long time = DateTimeUtil.getInt();
        if (stageFinishWorkDTO.getIsFinished() == 1) {
            //每完成一项阶段工作时的完成时间影响线索的最后跟进时间
            Boolean flag = proFormHelp.getClueSingleRuleList(corpid, ClueRuleSettingEnum.COMPLETE_PHASE_WORK_COMPLETION_TIME.getConfig(), formId);
            if (flag) {
                Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                map.put(ClueEnum.LAST_CONNECT_TIME.getAttr(), time);
                clueModel.jsonsetNoSubById(corpid, dataId, map);
                //评分更新 （线索阶段工作， 点击“完成工作”，如果表单设置了更新规则，那么会修改最后跟进时间）
                scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CLUE, corpid, dataId, null);
            }
        }
        return stageFinishWorkVO;
    }

    @Override
    public void stageWorkLogSave(StageWorkLogEntity stageWorkLogEntity) {
        ClueWorkLogEntity clueWorkLogEntity = new ClueWorkLogEntity();
        BeanUtils.copyProperties(stageWorkLogEntity, clueWorkLogEntity);
        clueWorkLogModel.save(clueWorkLogEntity);
    }

    @Override
    public List<StageWorkLogEntity> stageWorkLogFindEntitys(Map<String, Object> params) {
        List<ClueWorkLogEntity> entitys = clueWorkLogModel.findEntitys(params);
        return Arrays.asList(entitys.toArray(new StageWorkLogEntity[0]));
    }

    @Override
    public boolean checkshow(StageGetDTO stageGetDTO, PaasFormDataEntityExt paasFormDataEntityExt) throws XbbException {
        String corpid = stageGetDTO.getCorpid();
        Long dataId = stageGetDTO.getDataId();
        if (Objects.equals(stageGetDTO.getApproveType(), BasicConstant.ONE) || Objects.equals(stageGetDTO.getApproveType(), BasicConstant.TWO)) {
            return true;
        }
        if (Objects.isNull(paasFormDataEntityExt)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        Long formId = paasFormDataEntityExt.getFormId();
        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
        FieldAttrEntity stageEntity = explainMap.get(ClueEnum.CLUE_STAGE.getAttr());

        //协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        JSONObject data = paasFormDataEntityExt.getData();
        Boolean isPublic = data.getInteger(ClueEnum.IS_PUBLIC.getAttr()).equals(1);
        userTeamService.getUserIdMap(Collections.singletonList(paasFormDataEntityExt.getId()), corpid, XbbRefTypeEnum.CLUE.getCode(), isPublic, mainUserMap, coUserMap);
        // 当前数据的创建人、负责人、协同人、当前操作人
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(stageGetDTO, handlerExplainDTO);
        handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>()));
        handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>()));
        handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
        if (!CommonHelp.ifStageOpen(XbbRefTypeEnum.CLUE.getCode(), explainMap, handlerExplainDTO)) {
            return false;
        }
        if (Objects.nonNull(stageEntity)) {
            Integer stageProcessIdIsOpen = stageEntity.getIsOpen();
            Boolean fieldNeedHide = ExplainUtil.isFieldNeedHide(stageEntity, handlerExplainDTO);
            if (stageProcessIdIsOpen != 1 || fieldNeedHide) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean checkFieldEditable(SaasBaseDTO saasBaseDTO) throws XbbException {
        String corpid = saasBaseDTO.getCorpid();
        Integer businessType = saasBaseDTO.getBusinessType();
        Integer saasMark = saasBaseDTO.getSaasMark();
        Long dataId = saasBaseDTO.getDataId();
        PaasFormDataEntityExt paasFormDataEntityExt = (PaasFormDataEntityExt) proModelService.getFormDataEntity(corpid, saasMark, businessType, dataId);
        if (Objects.isNull(paasFormDataEntityExt)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
        }
        Long formId = paasFormDataEntityExt.getFormId();
        PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
        if (Objects.isNull(explain)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
        //协同团队
        Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        JSONObject data = paasFormDataEntityExt.getData();
        Boolean isPublic = data.getInteger(ClueEnum.IS_PUBLIC.getAttr()).equals(1);
        userTeamService.getUserIdMap(Collections.singletonList(paasFormDataEntityExt.getId()), corpid, XbbRefTypeEnum.CLUE.getCode(), isPublic, mainUserMap, coUserMap);
        // 当前数据的创建人、负责人、协同人、当前操作人
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        BeanUtil.copyProperties(saasBaseDTO, handlerExplainDTO);
        handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>()));
        handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(paasFormDataEntityExt.getId(), new ArrayList<>()));
        handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
        return ExplainUtil.isStageEdit(ClueEnum.CLUE_STAGE.getAttr(), explainMap, handlerExplainDTO);
    }

    @Override
    public void afterJumpDeal(StageJumpDealDTO stageJumpDealDTO, PaasFormDataEntityExt paasFormDataEntityExt) throws XbbException {
        if (!Objects.equals(stageJumpDealDTO.getIsImport(), 1)) {
            Runnable stageRemindTask = () -> addStageTimeOutRemind(stageJumpDealDTO, paasFormDataEntityExt);
            threadPoolBeanConfig.stageRemindThreadPool().execute(stageRemindTask);
        }

        PaasStageEntity toStageEntity = stageJumpDealDTO.getToStageEntity();
        Boolean isNew = stageJumpDealDTO.getIsNew();
        if (Objects.nonNull(isNew) && isNew) {
            return;
        }
        if (Objects.isNull(toStageEntity)) {
            toStageEntity = new PaasStageEntity();
            toStageEntity.setName("开始阶段");
            toStageEntity.setType(StageTypeEnum.START_STAGE.getType());
            toStageEntity.setBusinessRelatedStatus(-1);
        }
        PaasStageEntity fromStageEntity = stageJumpDealDTO.getFromStageEntity();
        String nowStageName = fromStageEntity == null ? "开始阶段" : fromStageEntity.getName();
        Integer clueStatus = toStageEntity.getBusinessRelatedStatus();
        String clueName = paasFormDataEntityExt.getData().getString(ClueEnum.COMPANY_NAME.getAttr());
        String stageName = toStageEntity.getName();
        Integer stageType = toStageEntity.getType();
        String corpid = stageJumpDealDTO.getCorpid();
        Long clueId = paasFormDataEntityExt.getDataId();
        Long formId = stageJumpDealDTO.getFormId();
        String userId = stageJumpDealDTO.getUserId();
        // 阶段推进器名称
        String stageAttrName = stageJumpDealDTO.getStageAttrName();
        //评分更新（线索阶段变更，修改线索状态）。上面使用了 clueModel.jsonsetNoSubById，要传输id重新查一遍
        scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CLUE, corpid, clueId, null);
        String preStageMemo = StringUtil.isEmpty(nowStageName) ? "" : I18nMessageUtil.getMessage(CommonConstant.BY) + "“" + nowStageName + "”";
        Runnable runnable = () -> {
            try {
                List<DetailLogPojo> detailArr = new ArrayList();
                // 生成项目日志
                String oldTitle = nowStageName;
                String newTitle = stageName;
                String newMsg = String.format(SymbolConstant.BRACKETS_SQUARE_SOLID, newTitle);
                String oldMsg = String.format(SymbolConstant.BRACKETS_SQUARE_SOLID, oldTitle);
                detailArr.add(new DetailLogPojo(stageAttrName, stageAttrName, oldMsg, newMsg));
                PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(formId, corpid);
                String logName = FastJsonHelper.getStringOrDefaultFromFormData(paasFormDataEntityExt.getData(), ClueEnum.COMPANY_NAME.getAttr(), "");
                String memo = String.format(I18nMessageUtil.getMessage(I18nStringConstant.STAGE_OPERATION_LOG), stageJumpDealDTO.getLoginUserName(),
                        paasFormEntityExt.getName(), logName);
                String opObjectName = logName;
                mongoLogHelp.buildLog4DetailArr(detailArr, corpid, stageJumpDealDTO.getUserId(), stageJumpDealDTO.getLoginUserName(),
                        OperateModuleTypeEnum.CLUE, OperateTypeEnum.EDIT, formId.toString(), opObjectName, memo, stageJumpDealDTO.getHttpHeader());

                String communicateMemo;
                if (Objects.equals(stageType, StageTypeEnum.FAIL_STAGE.getType())) {
                    //无效
                    Map<String, String> wastageReasonMap = dictionaryService.getDictionaryMap(DictionaryEnum.CLUE_STAGE_INVALID, corpid, formId);
                    String wastageReason = wastageReasonMap.get(stageJumpDealDTO.getReasonId().toString());
                    communicateMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.CHANGE_CLUE_STAGE), stageJumpDealDTO.getLoginUserName(), preStageMemo, stageName);
                    if (!StringUtil.isEmpty(wastageReason)) {
                        communicateMemo += "”，" + ClueEnum.INVALID_REASON.getAttrName() + "：" + wastageReason;
                    }
                    communicateMemo += "；" + stageJumpDealDTO.getMemo();
                } else {
                    communicateMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.CHANGE_CLUE_STAGE), stageJumpDealDTO.getLoginUserName(), preStageMemo, stageName);
                }
                customerCommunicateService.addCustomerDynamic(corpid, userId, communicateMemo, clueId, clueName, ProjectLogEnum.CLUE_STAGE.getSubType());

                // 线索阶段变更消息推送
                List<String> pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CLUE_STAGE.getCode(),
                        PushTypeEnum.CLUE_STAGE.getSubCode(), stageJumpDealDTO.getLoginUser(), paasFormDataEntityExt);
                PushRefTypePojo.Options options = null;
                MessageRabbitMqDTO messageRabbitMqDTO = null;
                if (CollectionsUtil.isNotEmpty(pushUserList)) {
                    options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(),
                            paasFormDataEntityExt.getFormId(), clueId, Collections.singletonList(clueId), SaasMarkEnum.SAAS.getCode(),
                            stageJumpDealDTO.getBusinessType(), stageJumpDealDTO.getBusinessType());
                    messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(clueId), 0,
                            null, I18nMessageUtil.getMessage(CluePushConstant.CLUE_STAGE_CHANGE_TITLE),
                            String.format(I18nMessageUtil.getMessage(CluePushConstant.CLUE_STAGE_CHANGE_CONTENT), stageJumpDealDTO.getLoginUserName(), clueName, stageName), null, options);
                    baseProducer.sendMessage(PushTypeEnum.CLUE_STAGE, messageRabbitMqDTO);
                }
                // 有关联线索的状态的才发消息
                if (Objects.nonNull(clueStatus)) {
                    ClueStatusEnum clueStatusEnum = ClueStatusEnum.getByCode(clueStatus.toString());
                    if (Objects.nonNull(clueStatusEnum)) {
                        String type = clueStatusEnum.getName();
                        pushUserList = pushHelper.getUserIdListByPushSetRule(corpid, PushTypeEnum.CLUE_CHANGE_PUSH.getCode(), PushTypeEnum.CLUE_CHANGE_PUSH.getSubCode(), stageJumpDealDTO.getLoginUser(), paasFormDataEntityExt);
                        if (CollectionsUtil.isNotEmpty(pushUserList)) {
                            options = new PushRefTypePojo.Options(paasFormDataEntityExt.getAppId(), paasFormDataEntityExt.getMenuId(), paasFormDataEntityExt.getFormId(), clueId, Collections.singletonList(clueId), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CLUE.getCode(), XbbRefTypeEnum.CLUE.getCode());
                            messageRabbitMqDTO = new MessageRabbitMqDTO(corpid, pushUserList, Collections.singletonList(clueId), 0, null, I18nMessageUtil.getMessage(CluePushConstant.CLUE_STATUS_CHANGE_TITLE), String.format(I18nMessageUtil.getMessage(CluePushConstant.CLUE_STATUS_CHANGE_CONTENT), stageJumpDealDTO.getLoginUserName(), clueName, type), null, options);
                            baseProducer.sendMessage(PushTypeEnum.CLUE_CHANGE_PUSH, messageRabbitMqDTO);
                        }
                    }
                }
            } catch (Exception e) {
                log.error("线索阶段变更消息推送", e);
            }
        };
        threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
    }

    @Override
    public Integer approvalRequired(CommonJumpDTO commonJumpDTO, PaasFormDataEntityExt paasFormDataEntityExt, String stageAttr) throws XbbException {
        Integer noApprovalRequired = 1;
        String corpid = commonJumpDTO.getCorpid();
        Long formId = commonJumpDTO.getFormId();
        Long clueId = paasFormDataEntityExt.getDataId();
        PaasStageEntity toStageEntity = commonJumpDTO.getToStageEntity();
        Integer reasonId = commonJumpDTO.getReasonId();
        String memo = commonJumpDTO.getMemo();
        String nextStageCode = "";
        Long nextStageId = 0L;
        Long nextStageProcessId = 0L;
        if (Objects.nonNull(toStageEntity)) {
            nextStageCode = toStageEntity.getCode();
            nextStageId = toStageEntity.getId();
            nextStageProcessId = toStageEntity.getStageProcessId();
        }
        if (commonHelp.isOpenWorkFlow(corpid)) {
            // 工作流
            List<WorkflowEntity> workflowEntities = workflowFormDataOperationService.getSatisfyTriggerEntitys(corpid, formId, XbbRefTypeEnum.CLUE.getCode(), Arrays.asList(TriggerEventTypeEnum.ONLY_UPDATE.getType(), TriggerEventTypeEnum.ADD_OR_UPDATE.getType()));
            for (WorkflowEntity workflowEntity : workflowEntities) {
                WorkflowNodeEntity startNode = workflowNodeModel.getByUId(workflowEntity.getId(), corpid, "startNode");
                FormTriggerNode formTriggerNode = JSON.parseObject(startNode.getConfigData(), FormTriggerNode.class);
                if (CollectionsUtil.isEmpty(formTriggerNode.getNeedApproveFields()) || formTriggerNode.getNeedApproveFields().contains(ClueEnum.CLUE_STAGE.getAttr())) {
                    //是否启用新工作流
                    PaasFormExplainEntity explain = paasFormExplainModel.getByFormId(formId, corpid);
                    Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(explain.getExplains(), null);
                    BusinessRuleInfoPojo businessRuleInfoPojo = new BusinessRuleInfoPojo(startNode.getCorpid(), startNode.getFormId(), startNode.getBusinessType(), startNode.getSaasMark(),explainMap);
                    PaasFormDataEntityExt paasFormDataEntityExtClone = (PaasFormDataEntityExt) CloneUtil.deepClone(paasFormDataEntityExt);
                    if (Objects.nonNull(toStageEntity)) {
                        // 详情页阶段跳转，用跳转之后的阶段去匹配触发条件-----59089 【KA大客户】【B级】阶段审批异常
                        paasFormDataEntityExtClone.getData().put(stageAttr, toStageEntity.getCode());
                    }
                    boolean flag = workflowFormDataOperationService.validatePreCondition(formTriggerNode.getTriggerConditions(), paasFormDataEntityExtClone, businessRuleInfoPojo);
                    if(!flag){
                        break;
                    }

                    workflowRequired(paasFormDataEntityExt, startNode, commonJumpDTO, WorkflowExecutionTypeEnum.FORM, stageAttr, null);
                    if (Objects.equals(1, workflowEntity.getIsApprove())) {
                        noApprovalRequired = 3;
                    } else {
                        // 无审批节点
                        noApprovalRequired = 4;
                    }
                    break;
                }
            }
        } else {
            // 老审批
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", 0);
            params.put("corpid", corpid);
            params.put("formId", formId);
            params.put("businessType", XbbRefTypeEnum.CLUE.getCode());
            params.put("enable", 1);
            List<PaasProcessTemplateEntityExt> paasProcessTemplateEntityExtList = paasProcessTemplateModel.list(params);
            if (paasProcessTemplateEntityExtList.size() > 0 && paasProcessTemplateEntityExtList.get(0).getNeedApproveFieldList().contains(ClueEnum.CLUE_STAGE.getAttr())) {
                JSONObject newData = (JSONObject) CloneUtil.deepClone(paasFormDataEntityExt.getData());
                newData.put(ClueEnum.CLUE_STAGE.getAttr(), nextStageCode == null ? "" : nextStageCode);
                newData.put(PaasStageEnum.STAGE_PROCESS_ID.getAttr(), nextStageProcessId);
                newData.put(PaasStageEnum.STAGE_ID.getAttr(), nextStageId);

                // 计算阶段比例
                StageJumpHandle stageJumpHandle = stageJumpMap.get(toStageEntity.getType());
                Integer proportion = stageJumpHandle.getJumpIntoProportion(paasFormDataEntityExt.getId(), corpid, formId, toStageEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CLUE.getCode(), toStageEntity.getOutProportion());
                newData.put(PaasStageEnum.STAGE_RATIO.getAttr(), proportion);
                Map<Integer, List<UserTeamEntity>> userMap = userTeamService.getUserTeam(paasFormDataEntityExt.getId(), corpid, XbbRefTypeEnum.CLUE.getCode());
                // 负责人
                if (userMap.containsKey(1)) {
                    List<UserTeamEntity> mainUserList = userMap.get(1);
                    List<String> mainIdList = new ArrayList<>();
                    for (UserTeamEntity userTeamEntity : mainUserList) {
                        mainIdList.add(userTeamEntity.getUserId());
                    }
                    newData.put(ClueEnum.OWNER_ID.getAttr(), mainIdList);
                }
                if (userMap.containsKey(0)) {
                    List<UserTeamEntity> coUserList = userMap.get(0);
                    List<String> coIdList = new ArrayList<>();
                    for (UserTeamEntity userTeamEntity : coUserList) {
                        coIdList.add(userTeamEntity.getUserId());
                    }
                    newData.put(ClueEnum.COUSERID.getAttr(), coIdList);
                }
                if (toStageEntity != null && Objects.equals(toStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType())) {
                    // 跳转到流失阶段，需要直接更改线索状态为无效，因为线索状态为无效时，才能展示下面这两个字段，审批时就能更改这两个字段的值
                    newData.put(ClueEnum.CLUE_STATUS.getAttr(), toStageEntity.getBusinessRelatedStatus().toString());
                    if (Objects.nonNull(reasonId)) {
                        newData.put(ClueEnum.INVALID_REASON.getAttr(), reasonId.toString());
                    }
                    newData.put(ClueEnum.INVALID_MEMO.getAttr(), memo);
                } else {
                    newData.put(ClueEnum.INVALID_REASON.getAttr(), "");
                    newData.put(ClueEnum.INVALID_MEMO.getAttr(), "");
                }
                StartProcessDTO startProcessDTO = new StartProcessDTO();
                BeanUtil.copyProperties(commonJumpDTO, startProcessDTO);
                BeanUtil.copyProperties(paasFormDataEntityExt, startProcessDTO);
                startProcessDTO.setData(newData);
                startProcessDTO.setFormDataId(paasFormDataEntityExt.getId());
                startProcessDTO.setCreatorId(commonJumpDTO.getUserId());
                startProcessDTO.setSaasMark(1);
                startProcessDTO.setBusinessType(XbbRefTypeEnum.CLUE.getCode());
                StartProcessVO startProcessVO = processStartHelp.startProcess(startProcessDTO, paasFormDataEntityExt);
                noApprovalRequired = startProcessVO.getNoApprovalRequired();
            }
        }
        return noApprovalRequired;
    }

    @Override
    public void workflowRequired(PaasFormDataEntityExt paasFormDataEntityExt, WorkflowNodeEntity startNode, CommonJumpDTO commonJumpDTO, WorkflowExecutionTypeEnum workflowExecutionTypeEnum, String stageAttr, WorkflowExecutionEntity workflowExecutionEntity) throws XbbException {
        String corpid = commonJumpDTO.getCorpid();
        Long formId = commonJumpDTO.getFormId();
        Long clueId = paasFormDataEntityExt.getDataId();
        PaasStageEntity toStageEntity = commonJumpDTO.getToStageEntity();
        Integer reasonId = commonJumpDTO.getReasonId();
        String memo = commonJumpDTO.getMemo();
        String nextStageCode = "";
        Long nextStageId = 0L;
        Long nextStageProcessId = 0L;
        Integer proportion = 0;
        if (Objects.nonNull(toStageEntity)) {
            nextStageCode = toStageEntity.getCode();
            nextStageId = toStageEntity.getId();
            nextStageProcessId = toStageEntity.getStageProcessId();
            // 计算阶段比例
            StageJumpHandle stageJumpHandle = stageJumpMap.get(toStageEntity.getType());
            proportion = stageJumpHandle.getJumpIntoProportion(paasFormDataEntityExt.getId(), corpid, formId, toStageEntity.getId(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.CLUE.getCode(), toStageEntity.getOutProportion());
        }

        // backup
        JSONObject oldDataObj = (JSONObject) CloneUtil.deepClone(paasFormDataEntityExt.getData());
        FormDataUtil.setSystemData(oldDataObj, paasFormDataEntityExt);
        long now = DateTimeUtil.getInt();
        List<ClueUserEntity> clueUserList = clueUserModel.getClueUserList(corpid, clueId, null);
        oldDataObj.put(StringConstant.USER_TEAM, clueUserList);
        WorkflowBackupDataEntity workflowBackupDataEntity = new WorkflowBackupDataEntity(corpid, paasFormDataEntityExt.getAppId(),
                paasFormDataEntityExt.getFormId(), paasFormDataEntityExt.getMenuId(), 0L, 0L, paasFormDataEntityExt.getId(), oldDataObj, now, now, DelEnum.NORMAL.getDel());
        workflowBackupDataModel.insert(workflowBackupDataEntity);

        //构建mq消息
        FormDataUtil.setSystemData(paasFormDataEntityExt.getData(), paasFormDataEntityExt);
        Data oldData = new Data(startNode.getAppId(), startNode.getMenuId(), startNode.getFormId(), paasFormDataEntityExt.getId(), oldDataObj, startNode.getBusinessType(), startNode.getSaasMark(), startNode.getId(), XbbRefTypeEnum.CLUE.getCode());
        // 将需要更新的字段，更新到主数据
        JSONObject updateDataJson = new JSONObject();

        updateDataJson.put(ClueEnum.CLUE_STAGE.getAttr(), nextStageCode == null ? "" : nextStageCode);
        if (toStageEntity != null && Objects.equals(toStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType())) {
            // 跳转到流失阶段，需要直接更改线索状态为无效，因为线索状态为无效时，才能展示下面这两个字段，审批时就能更改这两个字段的值
            updateDataJson.put(ClueEnum.CLUE_STATUS.getAttr(), toStageEntity.getBusinessRelatedStatus().toString());
            if (Objects.nonNull(reasonId)) {
                updateDataJson.put(ClueEnum.INVALID_REASON.getAttr(), reasonId.toString());
            }
            updateDataJson.put(ClueEnum.INVALID_MEMO.getAttr(), memo);
        } else {
            updateDataJson.put(ClueEnum.INVALID_REASON.getAttr(), "");
            updateDataJson.put(ClueEnum.INVALID_MEMO.getAttr(), "");
        }
        // 存放阶段流程id
        updateDataJson.put(PaasStageEnum.STAGE_PROCESS_ID.getAttr(), nextStageProcessId);
        // 存放阶段id
        updateDataJson.put(PaasStageEnum.STAGE_ID.getAttr(), nextStageId);

        updateDataJson.put(PaasStageEnum.STAGE_RATIO.getAttr(), proportion);
        // 更新数据
        UpdateDataEntity updateData = ExplainUtil.getUpdateData(clueId, updateDataJson, corpid);
        clueModel.updateBatch(Collections.singletonList(updateData), corpid, WriteRequest.RefreshPolicy.NONE);

        WorkflowTransferPOJO workflowTransferPOJO = WorkflowTransferHelp.createTransferData(paasFormDataEntityExt, null, null, null, corpid, commonJumpDTO.getLoginUser(), startNode, WorkflowOperateEnum.UPDATE.getType(), 0, XbbRefTypeEnum.CLUE.getCode());
        workflowTransferPOJO.setBackupDataId(workflowBackupDataEntity.getId());
        workflowTransferPOJO.setOldData(oldData);

        workflowTransferPOJO.setExecutionType(workflowExecutionTypeEnum.getCode());
        workflowTransferPOJO.setIsFromStage(true);
        workflowTransferPOJO.setToStageId(nextStageId);
        if (Objects.isNull(commonJumpDTO.getFromStageEntity())) {
            workflowTransferPOJO.setFromStageId(null);
        } else {
            workflowTransferPOJO.setFromStageId(commonJumpDTO.getFromStageEntity().getId());
        }
        if (!Objects.isNull(workflowExecutionEntity)) {
            workflowTransferPOJO.setParentExecutionId(workflowExecutionEntity.getId());
            workflowTransferPOJO.setLinkKey(workflowExecutionEntity.getLinkKey());
        }
        workflowTransferPOJO.setStageProcessId(commonJumpDTO.getStageProcessEntity().getId());

        JSONObject newDataObj = new JSONObject();
        newDataObj.putAll(oldDataObj);
        newDataObj.putAll(updateDataJson);
        Data newData = new Data(startNode.getAppId(), startNode.getMenuId(), startNode.getFormId(), paasFormDataEntityExt.getId(),
                newDataObj, startNode.getBusinessType(), startNode.getSaasMark(), startNode.getId(), XbbRefTypeEnum.CLUE.getCode());
        workflowTransferPOJO.setData(newData);

        WorkflowRabbitmqDTO workflowRabbitmqDTO = new WorkflowRabbitmqDTO(workflowTransferPOJO, startNode, null);
        workflowProducer.startWorkflow(workflowRabbitmqDTO);
    }

    @Override
    public void jumpSpecialDeal(StageJumpSpecialDealDTO stageJumpSpecialDealDTO) throws XbbException {
        String corpid = stageJumpSpecialDealDTO.getCorpid();
        Long dataId = stageJumpSpecialDealDTO.getDataId();
        Long formId = stageJumpSpecialDealDTO.getFormId();
        PaasStageEntity toStageEntity = stageJumpSpecialDealDTO.getToStageEntity();
        PaasStageEntity fromStageEntity = stageJumpSpecialDealDTO.getFromStageEntity();
        Integer saasMark = stageJumpSpecialDealDTO.getSaasMark();
        Integer businessType = stageJumpSpecialDealDTO.getBusinessType();
        Integer fromApproval = stageJumpSpecialDealDTO.getFromApproval();
        String nextStageCode = "";
        if (Objects.nonNull(toStageEntity)) {
            nextStageCode = toStageEntity.getCode();
        }
        // 线索的跳转特殊逻辑
        try {
            PaasFormDataEntityExt paasFormDataEntityExt = (PaasFormDataEntityExt) proModelService.getFormDataEntity(corpid, saasMark, businessType, dataId);
            //阶段跳转(含回退)中的跳转时间（取的是进入阶段的时间）影响最后跟进时间
            Boolean flag = proFormHelp.getClueSingleRuleList(corpid, ClueRuleSettingEnum.STAGE_JUMP_GO_TO_TIME.getConfig(), formId);
            if (flag) {
                Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                map.put(ClueEnum.LAST_CONNECT_TIME.getAttr(), DateTimeUtil.getInt());
                clueModel.jsonsetNoSubById(corpid, dataId, map);
                //下面已经处理了评分
            }
            //获取关联的线索状态
            Map<String, Object> updateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            //从无效跳转到非无效时，需要改下线索状态，否则不能继续进行线索转换
            if (Objects.nonNull(fromStageEntity) && Objects.equals(fromStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType())
                    && (Objects.isNull(toStageEntity) || !Objects.equals(toStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType()))) {
                updateMap.put(ClueEnum.CLUE_STATUS.getAttr(), ClueStatusEnum.PENDING.getCode());
            }
            if (/*!Objects.equals(1, fromApproval) &&*/ Objects.nonNull(toStageEntity) && Objects.equals(toStageEntity.getType(), StageTypeEnum.FAIL_STAGE.getType())) {
                //更改线索状态为无效，其它状态不修改
                Integer reasonId = stageJumpSpecialDealDTO.getReasonId();
                Integer clueStatus = toStageEntity.getBusinessRelatedStatus();
                updateMap.put(ClueEnum.CLUE_STATUS.getAttr(), clueStatus.toString());
                if (Objects.nonNull(reasonId)) {
                    updateMap.put(ClueEnum.INVALID_REASON.getAttr(), reasonId.toString());
                }
                updateMap.put(ClueEnum.INVALID_MEMO.getAttr(), stageJumpSpecialDealDTO.getMemo());
            } else {
                updateMap.put(ClueEnum.INVALID_REASON.getAttr(), "");
                updateMap.put(ClueEnum.INVALID_MEMO.getAttr(), "");
            }
            updateMap.put(ClueEnum.CLUE_STAGE.getAttr(), nextStageCode);

            clueModel.jsonsetNoSubById(corpid, dataId, updateMap);
            //下面已经处理了评分
            if (Objects.nonNull(paasFormDataEntityExt.getData().getLong(ClueEnum.MARKET_ACTIVITY_ID.getAttr()))) {
                PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                JSONObject jsonObject = new JSONObject();
                jsonObject.put(ClueEnum.CLUE_STAGE.getAttr(), nextStageCode);
                if (StringUtil.isNotEmpty(nextStageCode)) {
                    ClueStageEntity clueStage = clueStageModel.getByCode(corpid, formId, nextStageCode);
                    if (Objects.nonNull(clueStage) && Objects.equals(clueStage.getType(), StageTypeEnum.FAIL_STAGE.getType())) {
                        jsonObject.put(ClueEnum.CLUE_STATUS.getAttr(), ClueStatusEnum.INVALID.getCode());
                    }
                }
                jsonObject.put(ClueEnum.MARKET_ACTIVITY_ID.getAttr(), paasFormDataEntityExt.getData().getLong(ClueEnum.MARKET_ACTIVITY_ID.getAttr()));
                paasFormDataEntity.setCorpid(corpid);
                paasFormDataEntity.setId(dataId);
                paasFormDataEntity.setData(jsonObject);
                marketActivityForStaticHelp.updateMarketActivity(paasFormDataEntity, RedundantTemplateTypeEnum.CLUE);
            }
            //评分更新（线索阶段变更，修改线索状态）。上面使用了 clueModel.jsonsetNoSubById，要传输id重新查一遍
            scoreCalculateService.asyncUpdateSingleDataScore(XbbRefTypeEnum.CLUE, corpid, dataId, null);
        } catch (Exception e) {
            log.error("阶段跳转处理线索特殊逻辑出错", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }
}
